﻿/*
* Copyright (C)
* Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/* ScriptData
SDName: Karazhan
SD%Complete: 100
SDComment: Support for Barnes (Opera controller) and Berthold (Doorman), Support for Quest 9645.
SDCategory: Karazhan
EndScriptData */

/* ContentData
npc_barnes
npc_berthold
npc_image_of_medivh
EndContentData */

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "karazhan.h"
#include "ScriptedEscortAI.h"
#include "Player.h"
#pragma execution_character_set("utf-8")

enum Spells
{
	// Barnes
	SPELL_SPOTLIGHT = 25824,
	SPELL_TUXEDO = 32616,

	// Image of Medivh
	SPELL_FIRE_BALL = 30967,
	SPELL_UBER_FIREBALL = 30971,
	SPELL_CONFLAGRATION_BLAST = 30977,
	SPELL_MANA_SHIELD = 31635
};

enum Creatures
{
	NPC_ARCANAGOS = 17652,
	NPC_SPOTLIGHT = 19525
};

/*######
# npc_barnesAI
######*/

#define GOSSIP_READY        "我不是演员."

#define SAY_READY           "精彩，我要让观众准备好.断了一条腿!"
#define SAY_OZ_INTRO1       "最后，一切都在发生。你准备好为你的大舞台登场了吗?"
#define OZ_GOSSIP1          "我不是演员."
#define SAY_OZ_INTRO2       "别担心，你会好的。你看起来很自然!"
#define OZ_GOSSIP2          "好吧，那么我试试看."

#define SAY_RAJ_INTRO1      "浪漫的戏剧很难，但这一次你会做得更好。你有天赋。准备好了吗?"
#define RAJ_GOSSIP1         "我从来没有准备好."

#define OZ_GM_GOSSIP1       "[GM] Change event to EVENT_OZ"
#define OZ_GM_GOSSIP2       "[GM] Change event to EVENT_HOOD"
#define OZ_GM_GOSSIP3       "[GM] Change event to EVENT_RAJ"

struct Dialogue
{
	int32 textid;
	uint32 timer;
};

static Dialogue OzDialogue[] =
{
	{ 0, 6000 },
	{ 1, 18000 },
	{ 2, 9000 },
	{ 3, 15000 }
};

static Dialogue HoodDialogue[] =
{
	{ 4, 6000 },
	{ 5, 10000 },
	{ 6, 14000 },
	{ 7, 15000 }
};

static Dialogue RAJDialogue[] =
{
	{ 8, 5000 },
	{ 9, 7000 },
	{ 10, 14000 },
	{ 11, 14000 }
};

float GameObjects_OZ[5][4] =
{
	{ 183496, -10909.5f, -1761.79f, 90.477f }, //Bush
	{ 183496, -10906.7f, -1750.10f, 90.476f },
	{ 183496, -10883.0f, -1751.81f, 90.476f },
	{ 183496, -10877.7f, -1763.18f, 90.477f },
	{ 183442, -10890.9f, -1744.06f, 90.476f } //Scene Picture
};

float GameObjects_RomeJulia[1][4] =
{
	{ 183443, -10890.9f, -1744.06f, 90.476f }
};

float GameObjects_Wolf[5][4] =
{
	{ 183492, -10908.9f, -1762.55f, 90.478f },
	{ 183492, -10902.4f, -1753.36f, 90.477f },
	{ 183492, -10876.2f, -1761.21f, 90.477f },
	{ 183493, -10885.2f, -1756.47f, 90.477f },
	{ 183491, -10890.9f, -1744.06f, 90.476f }
};

// Entries and spawn locations for creatures in Oz event
float Spawns[6][2] =
{
	{ 17535, -10896 },                                        // Dorothee
	{ 17546, -10891 },                                        // Roar
	{ 17547, -10884 },                                        // Tinhead
	{ 17543, -10902 },                                        // Strawman
	{ 17603, -10892 },                                        // Grandmother
	{ 17534, -10900 },                                        // Julianne
};

#define SPAWN_Z             90.5f
#define SPAWN_Y             -1758
#define SPAWN_O             4.738f

class npc_barnes : public CreatureScript
{
public:
	npc_barnes() : CreatureScript("npc_barnes") { }

	struct npc_barnesAI : public npc_escortAI
	{
		npc_barnesAI(Creature* creature) : npc_escortAI(creature)
		{
			RaidWiped = false;
			m_uiEventId = 0;
			instance = creature->GetInstanceScript();
		}

		InstanceScript* instance;

		uint64 m_uiSpotlightGUID;

		uint32 TalkCount;
		uint32 TalkTimer;
		uint32 WipeTimer;
		uint32 m_uiEventId;

		bool PerformanceReady;
		bool RaidWiped;

		void Reset()
		{
			m_uiSpotlightGUID = 0;

			TalkCount = 0;
			TalkTimer = 2000;
			WipeTimer = 5000;

			PerformanceReady = false;

			m_uiEventId = instance->GetData(DATA_OPERA_PERFORMANCE);
		}

		void StartEvent()
		{
			instance->SetData(TYPE_OPERA, IN_PROGRESS);

			//resets count for this event, in case earlier failed
			if (m_uiEventId == EVENT_OZ)
				instance->SetData(DATA_OPERA_OZ_DEATHCOUNT, IN_PROGRESS);

			Start(false, false);
		}

		void EnterCombat(Unit* /*who*/) { }

		void WaypointReached(uint32 waypointId)
		{
			if (!instance)
				return;

			switch (waypointId)
			{
			case 0:
				DoCast(me, SPELL_TUXEDO, false);
				instance->DoUseDoorOrButton(instance->GetData64(DATA_GO_STAGEDOORLEFT));
				break;
			case 4:
				TalkCount = 0;
				SetEscortPaused(true);

				if (Creature* spotlight = me->SummonCreature(NPC_SPOTLIGHT,
					me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0.0f,
					TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000))
				{
					spotlight->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
					spotlight->CastSpell(spotlight, SPELL_SPOTLIGHT, false);
					m_uiSpotlightGUID = spotlight->GetGUID();
				}

				switch (m_uiEventId)
				{
				case EVENT_OZ:
					for (int i = 0; i<5; i++)
						me->SummonGameObject(GameObjects_OZ[i][0], GameObjects_OZ[i][1], GameObjects_OZ[i][2], GameObjects_OZ[i][3], 4.63f, 0, 0, 0.73f, -0.68f, 60000);
					break;
				case EVENT_HOOD:
					for (int i = 0; i<5; i++)
						me->SummonGameObject(GameObjects_Wolf[i][0], GameObjects_Wolf[i][1], GameObjects_Wolf[i][2], GameObjects_Wolf[i][3], 4.63f, 0, 0, 0.73f, -0.68f, 60000);
					break;
				case EVENT_RAJ:
					for (int i = 0; i<1; i++)
						me->SummonGameObject(GameObjects_RomeJulia[i][0], GameObjects_RomeJulia[i][1], GameObjects_RomeJulia[i][2], GameObjects_RomeJulia[i][3], 4.63f, 0, 0, 0.73f, -0.68f, 60000);
					break;
				}
				break;
			case 8:
				instance->DoUseDoorOrButton(instance->GetData64(DATA_GO_STAGEDOORLEFT));
				PerformanceReady = true;
				break;
			case 9:
				PrepareEncounter();
				instance->DoUseDoorOrButton(instance->GetData64(DATA_GO_CURTAINS));
				break;
			}
		}

		void Talk(uint32 count)
		{
			int32 text = 0;

			switch (m_uiEventId)
			{
			case EVENT_OZ:
				if (OzDialogue[count].textid)
					text = OzDialogue[count].textid;
				if (OzDialogue[count].timer)
					TalkTimer = OzDialogue[count].timer;
				break;

			case EVENT_HOOD:
				if (HoodDialogue[count].textid)
					text = HoodDialogue[count].textid;
				if (HoodDialogue[count].timer)
					TalkTimer = HoodDialogue[count].timer;
				break;

			case EVENT_RAJ:
				if (RAJDialogue[count].textid)
					text = RAJDialogue[count].textid;
				if (RAJDialogue[count].timer)
					TalkTimer = RAJDialogue[count].timer;
				break;
			}

			if (text)
				CreatureAI::Talk(text);
		}

		void PrepareEncounter()
		{
			;//sLog->outDebug(LOG_FILTER_TSCR, "TSCR: Barnes Opera Event - Introduction complete - preparing encounter %d", m_uiEventId);
			uint8 index = 0;
			uint8 count = 0;

			switch (m_uiEventId)
			{
			case EVENT_OZ:
				index = 0;
				count = 4;
				break;
			case EVENT_HOOD:
				index = 4;
				count = index + 1;
				break;
			case EVENT_RAJ:
				index = 5;
				count = index + 1;
				break;
			}

			for (; index < count; ++index)
			{
				uint32 entry = ((uint32)Spawns[index][0]);
				float PosX = Spawns[index][1];

				if (Creature* creature = me->SummonCreature(entry, PosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR * 2 * IN_MILLISECONDS))
				{
					// In case database has bad flags
					creature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
					creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
				}
			}

			RaidWiped = false;
		}

		void UpdateAI(uint32 diff)
		{
			npc_escortAI::UpdateAI(diff);

			if (HasEscortState(STATE_ESCORT_PAUSED))
			{
				if (TalkTimer <= diff)
				{
					if (TalkCount > 3)
					{
						if (Creature* pSpotlight = ObjectAccessor::GetCreature(*me, m_uiSpotlightGUID))
							pSpotlight->DespawnOrUnsummon();

						SetEscortPaused(false);
						return;
					}

					Talk(TalkCount);
					++TalkCount;
				}
				else TalkTimer -= diff;
			}

			if (PerformanceReady)
			{
				if (!RaidWiped)
				{
					if (WipeTimer <= diff)
					{
						Map* map = me->GetMap();
						if (!map->IsDungeon())
							return;

						Map::PlayerList const &PlayerList = map->GetPlayers();
						if (PlayerList.isEmpty())
							return;

						RaidWiped = true;
						for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
						{
							if (i->GetSource()->IsAlive() && !i->GetSource()->IsGameMaster())
							{
								RaidWiped = false;
								break;
							}
						}

						if (RaidWiped)
						{
							RaidWiped = true;
							EnterEvadeMode();
							return;
						}

						WipeTimer = 15000;
					}
					else WipeTimer -= diff;
				}
			}
		}
	};

	bool OnGossipHello(Player* player, Creature* creature)
	{
		if (InstanceScript* instance = creature->GetInstanceScript())
		{
			// Check for death of Moroes and if opera event is not done already
			if (instance->GetData(TYPE_MOROES) == DONE && instance->GetData(TYPE_OPERA) != DONE)
			{
				player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);

				if (player->IsGameMaster())
				{
					player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
					player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
					player->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
				}

				if (npc_barnesAI* pBarnesAI = CAST_AI(npc_barnes::npc_barnesAI, creature->AI()))
				{
					if (!pBarnesAI->RaidWiped)
						player->SEND_GOSSIP_MENU(8970, creature->GetGUID());
					else
						player->SEND_GOSSIP_MENU(8975, creature->GetGUID());

					return true;
				}
			}
		}

		player->SEND_GOSSIP_MENU(8978, creature->GetGUID());
		return true;
	}

	bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
	{
		player->PlayerTalkClass->ClearMenus();
		npc_barnesAI* pBarnesAI = CAST_AI(npc_barnes::npc_barnesAI, creature->AI());

		switch (action)
		{
		case GOSSIP_ACTION_INFO_DEF + 1:
			player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
			player->SEND_GOSSIP_MENU(8971, creature->GetGUID());
			break;
		case GOSSIP_ACTION_INFO_DEF + 2:
			player->CLOSE_GOSSIP_MENU();
			pBarnesAI->StartEvent();
			break;
		case GOSSIP_ACTION_INFO_DEF + 3:
			player->CLOSE_GOSSIP_MENU();
			pBarnesAI->m_uiEventId = EVENT_OZ;
			break;
		case GOSSIP_ACTION_INFO_DEF + 4:
			player->CLOSE_GOSSIP_MENU();
			pBarnesAI->m_uiEventId = EVENT_HOOD;
			break;
		case GOSSIP_ACTION_INFO_DEF + 5:
			player->CLOSE_GOSSIP_MENU();
			pBarnesAI->m_uiEventId = EVENT_RAJ;
			break;
		}

		return true;
	}

	CreatureAI* GetAI(Creature* creature) const
	{
		return new npc_barnesAI(creature);
	}
};

/*###
# npc_berthold
####*/

enum eBerthold
{
	SPELL_TELEPORT = 39567
};

#define GOSSIP_ITEM_PLACE        "这个地方是什么?"
#define GOSSIP_ITEM_MEDIVH       "哪里是麦迪文?"
#define GOSSIP_ITEM_TOWER        "你如何控制导航塔?"
#define GOSSIP_ITEM_TELEPORT    "瞬移到我的监护人的图书馆"

struct npc_bertholdAI : public ScriptedAI
{
	npc_bertholdAI(Creature* c) : ScriptedAI(c)
	{
		BowTimer = 0;
		canBow = false;
	}

	uint32 BowTimer;
	bool canBow;

	void SetBowTimer()
	{
		if (canBow)
			return;

		canBow = true;
		BowTimer = 250;
		me->HandleEmoteCommand(EMOTE_ONESHOT_BOW);
	}

	void UpdateAI(uint32 diff) override
	{
		if (!canBow)
			return;

		if (BowTimer < diff)
		{
			me->HandleEmoteCommand(EMOTE_ONESHOT_BOW);
			BowTimer = 0;
			canBow = false;
		}
		else
			BowTimer -= diff;
	}
};

CreatureAI* GetAI_npc_berthold(Creature *creature)
{
	return new npc_bertholdAI(creature);
}

bool GossipHello_npc_berthold(Player* player, Creature* creature)
{
	bool aranDone = false;
	if (InstanceScript* instance = creature->GetInstanceScript())
	{
		// Check if Shade of Aran event is done
		if (instance->GetData(TYPE_ARAN) == DONE)
			aranDone = true;
	}

	CAST_AI(npc_bertholdAI, creature->AI())->SetBowTimer();

	player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_PLACE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
	player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MEDIVH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
	player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TOWER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
	if (aranDone)
		player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TELEPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);

	if (aranDone)
		player->SEND_GOSSIP_MENU(25044, creature->GetGUID());
	else
		player->SEND_GOSSIP_MENU(25035, creature->GetGUID());

	return true;
}

bool GossipSelect_npc_berthold(Player* player, Creature* creature, uint32 /*uiSender*/, uint32 uiAction)
{
	switch (uiAction)
	{
	case GOSSIP_ACTION_INFO_DEF + 1:
		player->SEND_GOSSIP_MENU(25036, creature->GetGUID());
		break;
	case GOSSIP_ACTION_INFO_DEF + 2:
		player->SEND_GOSSIP_MENU(25037, creature->GetGUID());
		break;
	case GOSSIP_ACTION_INFO_DEF + 3:
		player->SEND_GOSSIP_MENU(25038, creature->GetGUID());
		break;
	case GOSSIP_ACTION_INFO_DEF + 4:
		player->CastSpell(player, SPELL_TELEPORT, true);
		player->CLOSE_GOSSIP_MENU();
		break;
	}

	return true;
}

/*###
# npc_calliard
####*/

#define GOSSIP_ITEM_MIDNIGHT    "谁是午夜?"

#define CALLIARD_SAY1           "谁在那里?"
#define CALLIARD_SAY2           "所有的宁静."
#define CALLIARD_SAY3           "我听到的东西?"

struct npc_calliardAI : public ScriptedAI
{
	npc_calliardAI(Creature* c) : ScriptedAI(c) {}

	uint32 Timer;

	void Reset()
	{
		Timer = 60000;
	}

	void UpdateAI(uint32 diff) override
	{
		if (Timer < diff)
		{
			me->MonsterYell(CALLIARD_SAY1, LANG_UNIVERSAL, NULL);
			me->MonsterYell(CALLIARD_SAY2, LANG_UNIVERSAL, NULL);
			me->MonsterYell(CALLIARD_SAY3, LANG_UNIVERSAL, NULL);
			Timer = urand(60000, 180000);
		}
		else
			Timer -= diff;

	}
};

CreatureAI* GetAI_npc_calliard(Creature *creature)
{
	return new npc_calliardAI(creature);
}

bool GossipHello_npc_calliard(Player* player, Creature* creature)
{
	player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_MIDNIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
	player->SEND_GOSSIP_MENU(25042, creature->GetGUID());

	return true;
}

bool GossipSelect_npc_calliard(Player* player, Creature* creature, uint32 sender, uint32 action)
{
	switch (action)
	{
	case GOSSIP_ACTION_INFO_DEF + 1:
		player->SEND_GOSSIP_MENU(25043, creature->GetGUID());
		break;
	}
	return true;
}

/*###
# npc_hastings
####*/

#define GOSSIP_ITEM_HELP    "需要我怎么帮助你?"
#define GOSSIP_ITEM_BIG     "大的?"

bool GossipHello_npc_hastings(Player* player, Creature* creature)
{
	player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_HELP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
	player->SEND_GOSSIP_MENU(25039, creature->GetGUID());

	return true;
}

bool GossipSelect_npc_hastings(Player* player, Creature* creature, uint32 sender, uint32 action)
{
	switch (action)
	{
	case GOSSIP_ACTION_INFO_DEF + 1:
		player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_BIG, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
		player->SEND_GOSSIP_MENU(25040, creature->GetGUID());
		break;
	case GOSSIP_ACTION_INFO_DEF + 2:
		player->SEND_GOSSIP_MENU(25041, creature->GetGUID());
		break;
	}
	return true;
}

/*###
# npc_image_of_medivh
####*/

#define SAY_DIALOG_MEDIVH_1         "你得到了我的关注,龙.你会发现我不像村民那么容易被吓到."
#define SAY_DIALOG_ARCANAGOS_2      "你涉足的神秘走得太远了,麦迪文.你已经吸引了超越你理解的力量的关注.你必须马上离开!"
#define SAY_DIALOG_MEDIVH_3         "你敢在我自己的住所挑战我吗？你的傲慢是惊人的,即使是龙!"
#define SAY_DIALOG_ARCANAGOS_4      "黑暗力量试图利用你,麦迪文！如果你停留,可怕的天会跟随.你必须匆忙,我们没有太多时间!"
#define SAY_DIALOG_MEDIVH_5         "我不知道你说什么,龙…但我不会因为这显示傲慢欺负.我会离开”当它适合我!"
#define SAY_DIALOG_ARCANAGOS_6      "你让我别无选择.如果你不听的话,我会阻止你的!"
#define EMOTE_DIALOG_MEDIVH_7       "开始施展大能的咒语,将自己的本质编织成魔术."
#define SAY_DIALOG_ARCANAGOS_8      "你做了什么,向导？这不能！我在燃烧…在内部!"
#define SAY_DIALOG_MEDIVH_9         "他不该惹我生气.我必须去…现在恢复我的力量..."

#define MOB_ARCANAGOS               17652
#define SPELL_FIRE_BALL             30967
#define SPELL_UBER_FIREBALL         30971
#define SPELL_CONFLAGRATION_BLAST   30977
#define SPELL_MANA_SHIELD           31635

static float MedivPos[4] = { -11161.49f, -1902.24f, 91.48f, 1.94f };
static float ArcanagosPos[4] = { -11169.75f, -1881.48f, 107.39f, 4.83f };

class npc_image_of_medivh : public CreatureScript
{
public:
	npc_image_of_medivh() : CreatureScript("npc_image_of_medivh") { }

	CreatureAI* GetAI(Creature* creature) const
	{
		return new npc_image_of_medivhAI(creature);
	}

	struct npc_image_of_medivhAI : public ScriptedAI
	{
		npc_image_of_medivhAI(Creature* c) : ScriptedAI(c)
		{
			instance = c->GetInstanceScript();
		}

		InstanceScript* instance;

		uint64 ArcanagosGUID;

		uint32 YellTimer;
		uint32 Step;
		uint32 FireMedivhTimer;
		uint32 FireArcanagosTimer;

		bool EventStarted;

		void Reset()
		{
			ArcanagosGUID = 0;

			if (instance && instance->GetData64(DATA_IMAGE_OF_MEDIVH) == 0)
			{
				instance->SetData64(DATA_IMAGE_OF_MEDIVH, me->GetGUID());
				(*me).GetMotionMaster()->MovePoint(1, MedivPos[0], MedivPos[1], MedivPos[2]);
				Step = 0;
			}
			else
			{
				me->DealDamage(me, me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
				me->RemoveCorpse();
			}
		}
		void EnterCombat(Unit* /*who*/) {}

		void MovementInform(uint32 type, uint32 id)
		{
			if (type != POINT_MOTION_TYPE)
				return;
			if (id == 1)
			{
				StartEvent();
				me->SetOrientation(MedivPos[3]);
				me->SetOrientation(MedivPos[3]);
			}
		}

		void StartEvent()
		{
			Step = 1;
			EventStarted = true;
			Creature* Arcanagos = me->SummonCreature(MOB_ARCANAGOS, ArcanagosPos[0], ArcanagosPos[1], ArcanagosPos[2], 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
			if (!Arcanagos)
				return;
			ArcanagosGUID = Arcanagos->GetGUID();
			Arcanagos->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_DISABLE_GRAVITY);
			(*Arcanagos).GetMotionMaster()->MovePoint(0, ArcanagosPos[0], ArcanagosPos[1], ArcanagosPos[2]);
			Arcanagos->SetOrientation(ArcanagosPos[3]);
			me->SetOrientation(MedivPos[3]);
			YellTimer = 10000;
		}

		uint32 NextStep(uint32 Step)
		{
			Unit* arca = ObjectAccessor::GetUnit((*me), ArcanagosGUID);
			Map* pMap = me->GetMap();
			switch (Step)
			{
			case 0: return 9999999;
			case 1:
				me->MonsterYell(SAY_DIALOG_MEDIVH_1, LANG_UNIVERSAL, NULL);
				return 10000;
			case 2:
				if (arca)
					arca->MonsterYell(SAY_DIALOG_ARCANAGOS_2, LANG_UNIVERSAL, NULL);
				return 20000;
			case 3:
				me->MonsterYell(SAY_DIALOG_MEDIVH_3, LANG_UNIVERSAL, NULL);
				return 10000;
			case 4:
				if (arca)
					arca->MonsterYell(SAY_DIALOG_ARCANAGOS_4, LANG_UNIVERSAL, NULL);
				return 20000;
			case 5:
				me->MonsterYell(SAY_DIALOG_MEDIVH_5, LANG_UNIVERSAL, NULL);
				return 20000;
			case 6:
				if (arca)
					arca->MonsterYell(SAY_DIALOG_ARCANAGOS_6, LANG_UNIVERSAL, NULL);
				return 10000;
			case 7:
				FireArcanagosTimer = 500;
				return 5000;
			case 8:
				FireMedivhTimer = 500;
				DoCast(me, SPELL_MANA_SHIELD);
				return 10000;
			case 9:
				me->MonsterTextEmote(EMOTE_DIALOG_MEDIVH_7, 0, false);
				return 10000;
			case 10:
				if (arca)
					DoCast(arca, SPELL_CONFLAGRATION_BLAST, false);
				return 1000;
			case 11:
				if (arca)
					arca->MonsterYell(SAY_DIALOG_ARCANAGOS_8, LANG_UNIVERSAL, NULL);
				return 5000;
			case 12:
				arca->GetMotionMaster()->MovePoint(0, -11010.82f, -1761.18f, 156.47f);
				arca->setActive(true);
				arca->InterruptNonMeleeSpells(true);
				arca->SetSpeed(MOVE_FLIGHT, 2.0f);
				return 10000;
			case 13:
				me->MonsterYell(SAY_DIALOG_MEDIVH_9, LANG_UNIVERSAL, NULL);
				return 10000;
			case 14:
				me->SetVisible(false);
				me->ClearInCombat();

				if (pMap->IsDungeon())
				{
					InstanceMap::PlayerList const &PlayerList = pMap->GetPlayers();
					for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
					{
						if (i->GetSource()->IsAlive())
						{
							if (i->GetSource()->GetQuestStatus(9645) == QUEST_STATUS_INCOMPLETE)
								i->GetSource()->CompleteQuest(9645);
						}
					}
				}
				return 50000;
			case 15:
				arca->DealDamage(arca, arca, arca->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
				return 5000;
			default: return 9999999;
			}
		}

		void UpdateAI(uint32 diff) override
		{
			if (YellTimer <= diff)
			{
				if (EventStarted)
					YellTimer = NextStep(Step++);
			}
			else YellTimer -= diff;

			if (Step >= 7 && Step <= 12)
			{
				Unit* arca = ObjectAccessor::GetUnit((*me), ArcanagosGUID);

				if (FireArcanagosTimer <= diff)
				{
					if (arca)
						arca->CastSpell(me, SPELL_FIRE_BALL, false);
					FireArcanagosTimer = 6000;
				}
				else FireArcanagosTimer -= diff;

				if (FireMedivhTimer <= diff)
				{
					if (arca)
						DoCast(arca, SPELL_FIRE_BALL);
					FireMedivhTimer = 5000;
				}
				else FireMedivhTimer -= diff;
			}
		}
	};
};

void AddSC_karazhan()
{
	new npc_barnes();
	new npc_image_of_medivh();
}
